﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using CarbonExchange.Bll;

namespace CarbonExchange.WebControls
{
    [ToolboxData("<{0}:AmeeDrillDown runat=server></{0}:AmeeDrillDown>")]
    public class AmeeDrillDown : CompositeControl, IPostBackEventHandler
    {
        public string Path { get; set; }

        public Label Label;
        public DropDownList DropDown { get; set; }
        public RequiredFieldValidator Validator { get; set; }

        private List<Option> _SelectedOptions = new List<Option>();
        public Option[] SelectedOptions
        {
            get
            {
                return _SelectedOptions.ToArray();
            }
        }
        
        public void AddOption(Option option)
        {
            currentCategory = null;
            _SelectedOptions.Add(option);
        }

        public void AddOptions(Option[] options)
        {
            if (options != null)
            {
                foreach (var option in options)
                    AddOption(option);
            }
        }

        public void ClearOptions()
        {
            currentCategory = null;
            _SelectedOptions.Clear();
        }

        private AmeeDataCatagory currentCategory;
        public AmeeDataCatagory CurrentCategory
        {
            get
            {
                if (currentCategory == null)
                {
                    AmeeDataCatagoryFactory factory = new AmeeDataCatagoryFactory();
                    var choices = _SelectedOptions.ToFormatedStringWithSpacer("&", x => x.Choice);
                    currentCategory = factory.GetByPath(Path, choices);
                }
                return currentCategory;
            }
        }

        protected override void CreateChildControls()
        {
            Label = new Label();
            Label.CssClass = "formLabel";
            Label.ID = "lblChildControl";

            Label.DataBinding += new EventHandler(Label_DataBinding);

            
            DropDown = new DropDownList();
            DropDown.ID = "ddlChildControl";
            DropDown.AutoPostBack = true;

            DropDown.SelectedIndexChanged += new EventHandler(DropDown_SelectedIndexChanged);
            DropDown.DataBinding += new EventHandler(DropDown_DataBinding);

            Validator = new RequiredFieldValidator();
            Validator.ID = "valChildControl";
            Validator.CssClass = "errror";
            Validator.ErrorMessage = "!";
            Validator.Display = ValidatorDisplay.Dynamic;
            Validator.ValidationGroup = "Save";
            
            Label.AssociatedControlID = DropDown.ID;
            Validator.ControlToValidate = DropDown.ID;

            this.Controls.Add(Label);
            this.Controls.Add(Validator);
            this.Controls.Add(DropDown);
            base.CreateChildControls();
        }

        public override void DataBind()
        {
            EnsureChildControls();
            if (CurrentCategory == null || CurrentCategory.DataItemSelected)
            {
                Label.Visible = false;
                DropDown.Visible = false;
            }
            base.DataBind();
        }

        void Label_DataBinding(object sender, EventArgs e)
        {
            if (LabelDataBinding != null)
                LabelDataBinding(this, new LabelDataBindingEventArgs(CurrentCategory, Label));
            
            Label.Text = GetChoiceDisplayText(CurrentCategory.ChoiceName);
            if (LabelDataBound != null)
                LabelDataBound(this, new LabelDataBindingEventArgs(CurrentCategory, Label));
        }

        void DropDown_DataBinding(object sender, EventArgs e)
        {
            DropDown.Items.Clear();
            if(CurrentCategory != null)
            {
                if (DropDownDataBinding != null)
                    DropDownDataBinding(this, new DropDownDataBindingEventArgs(CurrentCategory, DropDown));
                DropDown.Items.Add(new ListItem("", ""));
                var items = CurrentCategory.Choices.Select(x => new ListItem(GetChoiceDisplayText(x), string.Format("{0}={1}", CurrentCategory.ChoiceName, HttpUtility.UrlEncode(x)))).ToArray();
                DropDown.Items.AddRange(items);
                if (DropDownDataBound != null)
                    DropDownDataBound(this, new DropDownDataBindingEventArgs(CurrentCategory, DropDown));
            }
        }

        private string GetChoiceDisplayText(string choice)
        {
            if (choice != null)
                return choice.Split(' ').Select(x => string.Concat(x.Substring(0, 1).ToUpper(), x.Substring(1))).ToFormatedStringWithSpacer(" ", x => x);
            else
                return null;
        }

        void DropDown_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(DropDown.SelectedValue))
            {
                var tmp = new Option() { Choice = DropDown.SelectedValue, ChoiceText = DropDown.SelectedItem.Text, Label = Label.Text };
                _SelectedOptions.Add(tmp);
                currentCategory = null;
                OnItemSelected(new ItemSelectedEventArgs(CurrentCategory));
                if (CurrentCategory != null && CurrentCategory.DataItemSelected)
                {
                    Label.Visible = false;
                    DropDown.Visible = false;
                }
                else
                {
                    Label.Visible = true;
                    DropDown.Visible = true;
                    Label.DataBind();
                    DropDown.DataBind();
                }
            }
        }

        private void OnItemSelected(ItemSelectedEventArgs args)
        {
            if (ItemSelected != null)
            {
                ItemSelected(this, args);
            }
        }

        private string _FormItemClass = "formItem";
        public string FormItemClass 
        { 
            get {return _FormItemClass;}
            set { _FormItemClass = value; }
        }

        protected override void RenderContents(HtmlTextWriter writer)
        {
            foreach (var option in _SelectedOptions.Where(x => !x.Hidden))
            {

                writer.AddAttribute(HtmlTextWriterAttribute.Class, "ammeeItemHolder clearfix");
                writer.RenderBeginTag(HtmlTextWriterTag.Div);

                    writer.AddAttribute(HtmlTextWriterAttribute.Class, "ameeSelectionHolder");
                    writer.RenderBeginTag(HtmlTextWriterTag.Div);

                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "formLabel");
                        writer.RenderBeginTag(HtmlTextWriterTag.Span);
                        writer.Write(option.Label);
                        writer.RenderEndTag();

                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "ameeAnswerHolder clearfix");
                        writer.RenderBeginTag(HtmlTextWriterTag.Div);

                            //writer.Write("&nbsp;:&nbsp;");
                            writer.AddAttribute(HtmlTextWriterAttribute.Class, "ameeAnswer");
                            writer.RenderBeginTag(HtmlTextWriterTag.Span);
                            writer.Write(option.ChoiceText);
                            writer.RenderEndTag();

                            RenderRemoveLink(writer, _SelectedOptions.IndexOf(option));
                            
                        writer.RenderEndTag();
                    writer.RenderEndTag();
                writer.RenderEndTag();
            //writer.RenderEndTag();
            }
            if (Label.Visible == true && DropDown.Visible == true) {
                writer.AddAttribute(HtmlTextWriterAttribute.Class, string.Format("{0} clearfix", FormItemClass).Trim());
                writer.RenderBeginTag(HtmlTextWriterTag.Div);

                Validator.RenderControl(writer);
                Label.RenderControl(writer);
                    writer.AddAttribute(HtmlTextWriterAttribute.Class, "formInput");
                    writer.RenderBeginTag(HtmlTextWriterTag.Span);
                    DropDown.RenderControl(writer);
                    //writer.Write(DropDown.RenderControl);
                    //Label.RenderControl(writer);
                    writer.RenderEndTag();
                writer.RenderEndTag();

            }
            // base.RenderContents(writer);
        }

        private void RenderRemoveLink(HtmlTextWriter writer, int index)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Href, Page.ClientScript.GetPostBackClientHyperlink(this, index.ToString()));
            writer.AddAttribute(HtmlTextWriterAttribute.Class, "removeItem");
            writer.AddAttribute(HtmlTextWriterAttribute.Title, string.Format("Remove / Edit Selection"));
            writer.RenderBeginTag(HtmlTextWriterTag.A);
            
            //writer.Write("remove choice");

            writer.RenderEndTag();
        }

        public event EventHandler<LabelDataBindingEventArgs> LabelDataBinding;
        public event EventHandler<LabelDataBindingEventArgs> LabelDataBound;
        public class LabelDataBindingEventArgs : EventArgs
        {
            public LabelDataBindingEventArgs(AmeeDataCatagory category, Label label)
            {
                this.DataCatagory = category;
                this.Label = label;
            }

            public Label Label { get; private set; }
            public AmeeDataCatagory DataCatagory { get; private set; }
        }

        public event EventHandler<DropDownDataBindingEventArgs> DropDownDataBinding;
        public event EventHandler<DropDownDataBindingEventArgs> DropDownDataBound;
        public class DropDownDataBindingEventArgs : EventArgs
        {
            public DropDownDataBindingEventArgs(AmeeDataCatagory category, DropDownList dropDown)
            {
                this.DataCatagory = category;
                this.DropDown = dropDown;
            }

            public DropDownList DropDown { get; private set; }
            public AmeeDataCatagory DataCatagory { get; private set; }
        }

        public event EventHandler<ItemSelectedEventArgs> ItemSelected;
        public class ItemSelectedEventArgs : EventArgs
        {
            public ItemSelectedEventArgs(AmeeDataCatagory category)
            {
                this.DataCatagory = category;
            }

            public AmeeDataCatagory DataCatagory { get; private set; }
        }

        [Serializable]
        [Newtonsoft.Json.JsonObject()]
        public class Option
        {
            public Option()
            {
            }

            public string Label { get; set; }
            public string Choice { get; set; }
            public string ChoiceText { get; set; }
            public bool Hidden { get; set; }
        }

        protected override object SaveViewState()
        {
            ViewState["Path"] = Path;
            ViewState["SelectedOptions"] = _SelectedOptions;
            return base.SaveViewState();
        }

        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);
            Path = ViewState["Path"] as string;
            _SelectedOptions = ViewState["SelectedOptions"] as List<Option>;
        }


        #region IPostBackEventHandler Members

        public void RaisePostBackEvent(string eventArgument)
        {
            int index = int.Parse(eventArgument);
            _SelectedOptions.RemoveRange(index, _SelectedOptions.Count - index);
            currentCategory = null;
            OnItemSelected(new ItemSelectedEventArgs(CurrentCategory));
            Label.Visible = true;
            DropDown.Visible = true;
            Label.DataBind();
            DropDown.DataBind();
        }

        #endregion
    }
}
